home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / unix / tkUnixMenubu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  8.4 KB  |  308 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkUnixMenubu.c --
  3.  *
  4.  *    This file implements the Unix specific portion of the
  5.  *    menubutton widget.
  6.  *
  7.  * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tkUnixMenubu.c 1.9 97/05/23 16:25:01
  13.  */
  14.  
  15. #include "tkMenubutton.h"
  16.  
  17. /*
  18.  * The structure below defines menubutton class behavior by means of
  19.  * procedures that can be invoked from generic window code.
  20.  */
  21.  
  22. TkClassProcs tkpMenubuttonClass = {
  23.     NULL,            /* createProc. */
  24.     TkMenuButtonWorldChanged,    /* geometryProc. */
  25.     NULL            /* modalProc. */
  26. };
  27.  
  28. /*
  29.  *----------------------------------------------------------------------
  30.  *
  31.  * TkpCreateMenuButton --
  32.  *
  33.  *    Allocate a new TkMenuButton structure.
  34.  *
  35.  * Results:
  36.  *    Returns a newly allocated TkMenuButton structure.
  37.  *
  38.  * Side effects:
  39.  *    Registers an event handler for the widget.
  40.  *
  41.  *----------------------------------------------------------------------
  42.  */
  43.  
  44. TkMenuButton *
  45. TkpCreateMenuButton(tkwin)
  46.     Tk_Window tkwin;
  47. {
  48.     return (TkMenuButton *)ckalloc(sizeof(TkMenuButton));
  49. }
  50.  
  51. /*
  52.  *----------------------------------------------------------------------
  53.  *
  54.  * TkpDisplayMenuButton --
  55.  *
  56.  *    This procedure is invoked to display a menubutton widget.
  57.  *
  58.  * Results:
  59.  *    None.
  60.  *
  61.  * Side effects:
  62.  *    Commands are output to X to display the menubutton in its
  63.  *    current mode.
  64.  *
  65.  *----------------------------------------------------------------------
  66.  */
  67.  
  68. void
  69. TkpDisplayMenuButton(clientData)
  70.     ClientData clientData;    /* Information about widget. */
  71. {
  72.     register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
  73.     GC gc;
  74.     Tk_3DBorder border;
  75.     Pixmap pixmap;
  76.     int x = 0;            /* Initialization needed only to stop
  77.                  * compiler warning. */
  78.     int y;
  79.     register Tk_Window tkwin = mbPtr->tkwin;
  80.     int width, height;
  81.  
  82.     mbPtr->flags &= ~REDRAW_PENDING;
  83.     if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
  84.     return;
  85.     }
  86.  
  87.     if ((mbPtr->state == tkDisabledUid) && (mbPtr->disabledFg != NULL)) {
  88.     gc = mbPtr->disabledGC;
  89.     border = mbPtr->normalBorder;
  90.     } else if ((mbPtr->state == tkActiveUid) && !Tk_StrictMotif(mbPtr->tkwin)) {
  91.     gc = mbPtr->activeTextGC;
  92.     border = mbPtr->activeBorder;
  93.     } else {
  94.     gc = mbPtr->normalTextGC;
  95.     border = mbPtr->normalBorder;
  96.     }
  97.  
  98.     /*
  99.      * In order to avoid screen flashes, this procedure redraws
  100.      * the menu button in a pixmap, then copies the pixmap to the
  101.      * screen in a single operation.  This means that there's no
  102.      * point in time where the on-sreen image has been cleared.
  103.      */
  104.  
  105.     pixmap = Tk_GetPixmap(mbPtr->display, Tk_WindowId(tkwin),
  106.         Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
  107.     Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),
  108.         Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
  109.  
  110.     /*
  111.      * Display image or bitmap or text for button.
  112.      */
  113.  
  114.     if (mbPtr->image != None) {
  115.     Tk_SizeOfImage(mbPtr->image, &width, &height);
  116.  
  117.     imageOrBitmap:
  118.     TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, 
  119.         width + mbPtr->indicatorWidth, height, &x, &y);
  120.     if (mbPtr->image != NULL) {
  121.         Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,
  122.             x, y);
  123.     } else {
  124.         XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,
  125.             gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1);
  126.     }
  127.     } else if (mbPtr->bitmap != None) {
  128.     Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  129.     goto imageOrBitmap;
  130.     } else {
  131.     TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY,
  132.         mbPtr->textWidth + mbPtr->indicatorWidth,
  133.         mbPtr->textHeight, &x, &y);
  134.     Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x, y,
  135.         0, -1);
  136.     Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,
  137.         x, y, mbPtr->underline);
  138.     }
  139.  
  140.     /*
  141.      * If the menu button is disabled with a stipple rather than a special
  142.      * foreground color, generate the stippled effect.
  143.      */
  144.  
  145.     if ((mbPtr->state == tkDisabledUid)
  146.         && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) {
  147.     XFillRectangle(mbPtr->display, pixmap, mbPtr->disabledGC,
  148.         mbPtr->inset, mbPtr->inset,
  149.         (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset),
  150.         (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset));
  151.     }
  152.  
  153.     /*
  154.      * Draw the cascade indicator for the menu button on the
  155.      * right side of the window, if desired.
  156.      */
  157.  
  158.     if (mbPtr->indicatorOn) {
  159.     int borderWidth;
  160.  
  161.     borderWidth = (mbPtr->indicatorHeight+1)/3;
  162.     if (borderWidth < 1) {
  163.         borderWidth = 1;
  164.     }
  165.     /*y += mbPtr->textHeight / 2;*/
  166.     Tk_Fill3DRectangle(tkwin, pixmap, border,
  167.         Tk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth
  168.         + mbPtr->indicatorHeight,
  169.         ((int) (Tk_Height(tkwin) - mbPtr->indicatorHeight))/2,
  170.         mbPtr->indicatorWidth - 2*mbPtr->indicatorHeight,
  171.         mbPtr->indicatorHeight, borderWidth, TK_RELIEF_RAISED);
  172.     }
  173.  
  174.     /*
  175.      * Draw the border and traversal highlight last.  This way, if the
  176.      * menu button's contents overflow onto the border they'll be covered
  177.      * up by the border.
  178.      */
  179.  
  180.     if (mbPtr->relief != TK_RELIEF_FLAT) {
  181.     Tk_Draw3DRectangle(tkwin, pixmap, border,
  182.         mbPtr->highlightWidth, mbPtr->highlightWidth,
  183.         Tk_Width(tkwin) - 2*mbPtr->highlightWidth,
  184.         Tk_Height(tkwin) - 2*mbPtr->highlightWidth,
  185.         mbPtr->borderWidth, mbPtr->relief);
  186.     }
  187.     if (mbPtr->highlightWidth != 0) {
  188.     GC gc;
  189.  
  190.     if (mbPtr->flags & GOT_FOCUS) {
  191.         gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap);
  192.     } else {
  193.         gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap);
  194.     }
  195.     Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth, pixmap);
  196.     }
  197.  
  198.     /*
  199.      * Copy the information from the off-screen pixmap onto the screen,
  200.      * then delete the pixmap.
  201.      */
  202.  
  203.     XCopyArea(mbPtr->display, pixmap, Tk_WindowId(tkwin),
  204.         mbPtr->normalTextGC, 0, 0, (unsigned) Tk_Width(tkwin),
  205.         (unsigned) Tk_Height(tkwin), 0, 0);
  206.     Tk_FreePixmap(mbPtr->display, pixmap);
  207. }
  208.  
  209. /*
  210.  *----------------------------------------------------------------------
  211.  *
  212.  * TkpDestroyMenuButton --
  213.  *
  214.  *    Free data structures associated with the menubutton control.
  215.  *
  216.  * Results:
  217.  *    None.
  218.  *
  219.  * Side effects:
  220.  *    Restores the default control state.
  221.  *
  222.  *----------------------------------------------------------------------
  223.  */
  224.  
  225. void
  226. TkpDestroyMenuButton(mbPtr)
  227.     TkMenuButton *mbPtr;
  228. {
  229. }
  230.  
  231. /*
  232.  *----------------------------------------------------------------------
  233.  *
  234.  * TkpComputeMenuButtonGeometry --
  235.  *
  236.  *    After changes in a menu button's text or bitmap, this procedure
  237.  *    recomputes the menu button's geometry and passes this information
  238.  *    along to the geometry manager for the window.
  239.  *
  240.  * Results:
  241.  *    None.
  242.  *
  243.  * Side effects:
  244.  *    The menu button's window may change size.
  245.  *
  246.  *----------------------------------------------------------------------
  247.  */
  248.  
  249. void
  250. TkpComputeMenuButtonGeometry(mbPtr)
  251.     register TkMenuButton *mbPtr;    /* Widget record for menu button. */
  252. {
  253.     int width, height, mm, pixels;
  254.  
  255.     mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth;
  256.     if (mbPtr->image != None) {
  257.     Tk_SizeOfImage(mbPtr->image, &width, &height);
  258.     if (mbPtr->width > 0) {
  259.         width = mbPtr->width;
  260.     }
  261.     if (mbPtr->height > 0) {
  262.         height = mbPtr->height;
  263.     }
  264.     } else if (mbPtr->bitmap != None) {
  265.     Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
  266.     if (mbPtr->width > 0) {
  267.         width = mbPtr->width;
  268.     }
  269.     if (mbPtr->height > 0) {
  270.         height = mbPtr->height;
  271.     }
  272.     } else {
  273.     Tk_FreeTextLayout(mbPtr->textLayout);
  274.     mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text,
  275.         -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,
  276.         &mbPtr->textHeight);
  277.     width = mbPtr->textWidth;
  278.     height = mbPtr->textHeight;
  279.     if (mbPtr->width > 0) {
  280.         width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1);
  281.     }
  282.     if (mbPtr->height > 0) {
  283.         Tk_FontMetrics fm;
  284.  
  285.         Tk_GetFontMetrics(mbPtr->tkfont, &fm);
  286.         height = mbPtr->height * fm.linespace;
  287.     }
  288.     width += 2*mbPtr->padX;
  289.     height += 2*mbPtr->padY;
  290.     }
  291.  
  292.     if (mbPtr->indicatorOn) {
  293.     mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
  294.     pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
  295.     mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm);
  296.     mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm)
  297.         + 2*mbPtr->indicatorHeight;
  298.     width += mbPtr->indicatorWidth;
  299.     } else {
  300.     mbPtr->indicatorHeight = 0;
  301.     mbPtr->indicatorWidth = 0;
  302.     }
  303.  
  304.     Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset),
  305.         (int) (height + 2*mbPtr->inset));
  306.     Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset);
  307. }
  308.